<template>
  <div class="ctView">
    <vHeader />
    <vBottomTwo :handleBottomBox="handleBottomBox" @sixView="sixView" :ct="ct"/>
    <vBottom :handleBottomBox="handleBottomBox"/>
    <div ref="ctBox" class="ctBox" :style="{flexDirection:isLandscape?'row':'column'}" v-loading="ct.loading">
      <div class="screen3d" ref="screen3d"></div>
      <div class="screenct" ref="screenct"></div>
      <!-- <div class="screenct" ref="screenct" :style="styleFilter"></div> -->
    </div>
  </div>
</template>

<script>

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

import JsZip from "jszip"
import html2canvas from "html2canvas"

import {deepCopy} from '@/utils/tools/tools'

import vHeader from './pub/v-header'
import vBottom from './ctView/v-bottom'
import vBottomTwo from './ctView/v-bottom-two'

import {downloadFile} from '@/depends/api/file'


let canvas = null
let ctCanvas = null
let ctx = null
let ctImageData = null
let threeObj = {
  renderer: null,
  controls: null,
  scene: null,
  camera: null,
  groupModel: null,
  content: {
    ambientLight: null,
  }
}

let touch = {
  start: {
    x: 0,
    y: 0
  },
  move: {
    x: 0,
    y: 0
  },

}

export default {
  components: {
    vHeader,
    vBottom,
    vBottomTwo
  },
  data() {
    return {
      isLandscape: true,
      modelPlane: [],
      handleBottomBox: {
        curImg: {
          flag: false
        },
        brightnessFrom: {
          flag: false,
          val: 0
        },
        contrastFrom: {
          flag: false,
          val: 0
        },
        sixView: {
          flag: false,
        }
      },
      ct: {
        loading: false,
        isPlay: false,
        maxZ: 0,
        indexZ: 1,
        imagesZ: [],
        thickness: 0,
        timer: 0
      }
    };
  },
  props: ['ctLists'],
  computed:{
    styleFilter () {
      return {filter: `contrast(${this.handleBottomBox.contrastFrom.val}%) brightness(${this.handleBottomBox.brightnessFrom.val}%)`}
    },
    bottomTwoShow () {
      let flag = false
      for (let a in this.handleBottomBox) {
        if (this.handleBottomBox[a].flag) { flag = true }
      }
      return flag
    }
  },
  created () {
    this.ct.thickness = this.ctLists[0].ctLayerThickness || 1
    this.ct.maxZ = this.ctLists[0].ctMaxZ || 0
  },
  mounted() {
    this._w_h()
    this.initct()
    this.initThree()

    window.addEventListener( 'resize', this.onWindowResize );
  },
  methods:{
    sixView (type) {

      let box = new THREE.Box3().setFromObject(threeObj.groupModel)
      const center = box.getCenter( new THREE.Vector3() )
      let boxSize = box.size()
      // let max  = parseInt(Math.max(...Object.values(box.size())))
      let n = 2.4
      switch (type) {
        case 1:
        // 前
        threeObj.camera.position.set(center.x, -boxSize.z*n + center.y, center.z )
        break;
        case 2:
        // 后
        threeObj.camera.position.set(center.x, boxSize.z*n + center.y, center.z )
        break;
        case 3:
        // 左
        threeObj.camera.position.set(boxSize.z*n + center.x, center.y, center.z )
        break;
        case 4:
        // 右
        threeObj.camera.position.set(-boxSize.z*n + center.x, center.y, center.z )
        break;
        case 5:
        // 上
        threeObj.camera.position.set(center.x, center.y, boxSize.y*n + center.z )
        break;
        case 6:
        // 下
        threeObj.camera.position.set(center.x, center.y, -boxSize.y*n + center.z )
        break;
      }
      threeObj.controls.update();
    },
    initThree() {
      const win = this._w_h()

      threeObj.renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true, antialias: true })
      threeObj.renderer.setPixelRatio(window.devicePixelRatio);
      threeObj.renderer.setSize(win.w, win.h);

      this.modelPlane = [new THREE.Plane( new THREE.Vector3( 0, 0, -1 ), 0 )];
      threeObj.renderer.clippingPlanes = this.modelPlane
      // threeObj.renderer.localClippingEnabled = true;

      this.$refs.screen3d.appendChild(threeObj.renderer.domElement);

      threeObj.scene = new THREE.Scene();
      threeObj.scene.background = new THREE.Color(0x000000);
      threeObj.scene.add( new THREE.AmbientLight( 0xffffff, 0.2 ) );

      threeObj.camera = new THREE.PerspectiveCamera(45, win.w/win.h, 50, 10000);
      threeObj.camera.add( new THREE.PointLight( 0xffffff, 0.8 ) );
      threeObj.camera.up.set( 0, 0, 1 );
      threeObj.scene.add( threeObj.camera );


      threeObj.controls = new OrbitControls(threeObj.camera, threeObj.renderer.domElement);
      threeObj.controls.target.set( 0, 0, 0 );
      threeObj.controls.update();
      threeObj.controls.addEventListener( 'change', this.render );

    },
    resetXYZ () {
      // threeObj.renderer.constant = parseInt(20)
      let box = new THREE.Box3().setFromObject(threeObj.groupModel)

      // this.modelPlane[0].constant = 80

      const center = box.getCenter( new THREE.Vector3() )
      threeObj.controls.target.x += ( threeObj.controls.target.x + center.x );
      threeObj.controls.target.y += ( threeObj.controls.target.y + center.y );
      threeObj.controls.target.z += ( threeObj.controls.target.z + center.z );

      // console.log(new THREE.Box3().setFromObject(threeObj.groupModel),threeObj.controls.target)

      let boxSize = box.size()

      threeObj.camera.position.set(threeObj.controls.target.x, -boxSize.z*2.4 + threeObj.controls.target.y, threeObj.controls.target.z )

      threeObj.camera.updateProjectionMatrix();
      threeObj.controls.update();
      this.render();
    },
    render() {
      threeObj.renderer.render( threeObj.scene, threeObj.camera );

    },
    touchstart (e) {
      if (e.touches) {
        if (e.touches.length>1) { return }
        e.clientX = e.touches[0].clientX
        e.clientY = e.touches[0].clientY
      }
      touch.start.x = e.clientX
      touch.start.y = e.clientY
    },
    touchmove (e) {
      if (touch.start.x === 0 && touch.start.y === 0) { return }
      if (e.touches) {
        if (e.touches.length>1) { return }
        e.clientX = e.touches[0].clientX
        e.clientY = e.touches[0].clientY
      }
      touch.move.x = e.clientX
      touch.move.y = e.clientY

      this.showImage(this.ct.indexZ)
    },
    touchend (e) {
      if (touch.start.x === 0 && touch.start.y === 0) { return }
      if (touch.move.x === 0 && touch.move.y === 0) { return }
      const touchREXT = 4
      const movex = parseInt((touch.move.x - touch.start.x) / touchREXT)
      const movey = parseInt(- (touch.move.y - touch.start.y) / touchREXT)
      let [a, b] = [this.handleBottomBox.brightnessFrom.val, this.handleBottomBox.contrastFrom.val]

      if (a + movex > 100) { a = 100 } else if (a + movex < -100) { a = -100 } else { a = a + movex }
      if (b + movey > 200) { b = 200 } else if (b + movey < -200) { b = -200 } else { b = b + movey }
      this.handleBottomBox.brightnessFrom.val = a
      this.handleBottomBox.contrastFrom.val = b
      this.showImage(this.ct.indexZ)

      touch = {
        start: {
          x: 0,
          y: 0
        },
        move: {
          x: 0,
          y: 0
        },
      }
    },
    initct () {
      this.ct.loading = true
      ctCanvas = document.createElement('canvas')
      ctCanvas.style.backgroundColor = '#000'
      const win = this._w_h()
      ctCanvas.width = win.w
      ctCanvas.height = win.h
      this.$refs.screenct.appendChild(ctCanvas)

      ctCanvas.addEventListener('touchstart', this.touchstart, false)
      ctCanvas.addEventListener('touchmove', this.touchmove, false)
      ctCanvas.addEventListener('touchend', this.touchend, false)


      ctCanvas.addEventListener('mousedown', this.touchstart, false)
      ctCanvas.addEventListener('mousemove', this.touchmove, false)
      ctCanvas.addEventListener('mouseup', this.touchend, false)

      ctx = ctCanvas.getContext('2d')

      downloadFile({fileName: this.ctLists[0].url}).then(res => {
        JsZip.loadAsync(res.data).then((zip) => {
          Promise.all(Object.values(zip.files).map(a => a.async("base64"))).then((base64s) => {
            base64s.forEach((a,b) => {
              let image = new Image()
              image.src = `data:image/jpg;base64,${a}`
              this.ct.imagesZ.push(image)
              this.ct.loading = false
            })
            if (this._w_h().w) { this.showImage(this.ct.indexZ) }
          })
        })
      })
    },
    showOne() {
      this.$nextTick(() => {
        this.onWindowResize()
      })
    },
    showImage (i) {
      i--
      if(this.ct.imagesZ[i] === undefined) { return }
      const win = this._w_h()
      const min = Math.min(...Object.values(win))
      ctx.clearRect(0, 0, win.w, win.h)
      this.$nextTick(() => {
        ctx.drawImage(
          this.ct.imagesZ[this.ct.imagesZ.length - i - 1],
          0, 0,
          this.ct.imagesZ[i].width, this.ct.imagesZ[i].height,
          (win.w-min)/2, (win.h-min)/2,
          min, min
        )
        if (!ctCanvas.width) { return }
        this.$nextTick(() => {
          ctImageData = deepCopy(ctx.getImageData(0,0,ctCanvas.width,ctCanvas.height).data)
          this.setBrightnessContrastFrom(this.handleBottomBox.brightnessFrom.val, this.handleBottomBox.contrastFrom.val)
        })
      })
      if (threeObj.groupModel) {
        let curz = this.ct.maxZ - this.ct.thickness * i
        this.modelPlane[0].constant = curz
        this.render();
      }
    },
    goPlay () {
      this.ct.isPlay = !this.ct.isPlay
      if (this.ct.isPlay) {
        if (this.ct.indexZ == this.ct.imagesZ.length) { this.ct.indexZ = 1}
        this.palyer()
      } else {
        clearTimeout(this.ct.timer)
      }
    },
    palyer () {
        if (this.ct.indexZ == this.ct.imagesZ.length) { this.ct.isPlay = false;clearTimeout(this.ct.timer);return }
        this.ct.timer = setTimeout(() => {
          this.ct.indexZ++
          this.showImage(this.ct.indexZ)
          this.palyer()
        }, 100)
    },
    setIndex (a) {
      this.ct.indexZ = a
      if (this.ct.imagesZ.length) this.showImage(this.ct.indexZ)
      
    },
    onBlur () {
      window.scrollTo(0, 0)
    },
    setBrightness (a) {
      // 亮度
      if (!ctImageData) { return }
      this.setBrightnessContrastFrom(this.handleBottomBox.brightnessFrom.val, this.handleBottomBox.contrastFrom.val)
      // return
      // const longStep = 2.55 * a
      // let newImageData = ctx.getImageData(0, 0, ctCanvas.width, ctCanvas.height)
      // for (let i = 0; i < newImageData.data.length - 4; i += 4) {
      //   newImageData.data[i] = ctImageData[i] + longStep > 255 ? 255 : ctImageData[i] + longStep
      //   newImageData.data[i + 1] = ctImageData[i + 1] + longStep > 255 ? 255 : ctImageData[i + 1] + longStep
      //   newImageData.data[i + 2] = ctImageData[i + 2] + longStep > 255 ? 255 : ctImageData[i + 2] + longStep
      //   newImageData.data[i + 3] = 255
      // }
      // ctx.putImageData(newImageData, 0, 0);
    },
    setContrastFrom (a) {
      // 对比度
      if (!ctImageData) { return }
      this.setBrightnessContrastFrom(this.handleBottomBox.brightnessFrom.val, this.handleBottomBox.contrastFrom.val)
      // return
      // const longStep = 50
      // let newImageData = ctx.getImageData(0, 0, ctCanvas.width, ctCanvas.height)
      // for (let i = 0; i < newImageData.data.length - 4; i += 4) {
      //   newImageData.data[i] = ctImageData[i] + (ctImageData[i] - longStep) * (1 / (1 - a / 255) - 1)
      //   newImageData.data[i + 1] = ctImageData[i + 1] + (ctImageData[i + 1] - longStep) * (1 / (1 - a / 255) - 1)
      //   newImageData.data[i + 2] = ctImageData[i + 2] + (ctImageData[i + 2] - longStep) * (1 / (1 - a / 255) - 1)
      //   newImageData.data[i + 3] = 255
      // }
      // ctx.putImageData(newImageData, 0, 0);

// 1、计算平均亮度

// 2、每点与平均亮度比较，得到差值。

// 3、新的亮度 = 平均亮度 + 系数 * 差值

// 4、根据新的亮度，计算出新的rgb(保持色调不变)

    },
    setBrightnessContrastFrom(a, b) {
      const touchREXT = 4
      const movex = parseInt((touch.move.x - touch.start.x) / touchREXT)
      const movey = parseInt(- (touch.move.y - touch.start.y) / touchREXT)

      if (a + movex > 100) { a = 100 } else if (a + movex < -100) { a = -100 } else { a = a + movex }
      if (b + movey > 200) { b = 200 } else if (b + movey < -200) { b = -200 } else { b = b + movey }

      const longStep = 2.55 * a
      const factor = 20

      if (!ctCanvas.width) { return }
      let newImageData = ctx.getImageData(0, 0, ctCanvas.width, ctCanvas.height)
      for (let i = 0; i < newImageData.data.length - 4; i += 4) {
        newImageData.data[i] = ctImageData[i] + longStep > 255 ? 255 : ctImageData[i] + longStep
        newImageData.data[i + 1] = ctImageData[i + 1] + longStep > 255 ? 255 : ctImageData[i + 1] + longStep
        newImageData.data[i + 2] = ctImageData[i + 2] + longStep > 255 ? 255 : ctImageData[i + 2] + longStep


        newImageData.data[i] = newImageData.data[i] + (newImageData.data[i] - factor) * (1 / (1 - b / 255) - 1)
        newImageData.data[i + 1] = newImageData.data[i + 1] + (newImageData.data[i + 1] - factor) * (1 / (1 - b / 255) - 1)
        newImageData.data[i + 2] = newImageData.data[i + 2] + (newImageData.data[i + 2] - factor) * (1 / (1 - b / 255) - 1)


        newImageData.data[i + 3] = 255
      }
      ctx.putImageData(newImageData, 0, 0);
    },
    clipPic () {
      // this.$emit('upDate', 'ctScreenshot', 255, this.$refs.screenct.querySelector('canvas').toDataURL())

      return new Promise((resolve, reject) => {

        // let labelBoxAll = document.querySelectorAll('.labelBox')
        // let transforms = []
        // labelBoxAll.forEach((a, b) => {
        //   transforms.push(a.style.transform)
        //    const _tf = a.style.transform.match(/(\d*\.?\d*)/g).filter(x => x)
        //    a.style.transform = ''
        //    a.style.top = `${-a.offsetHeight/2 + Number(_tf[3])}px`
        //    a.style.left = `${-a.offsetWidth/2 + Number(_tf[2])}px`
        // })
        html2canvas(this.$refs.ctBox, {scale: window.devicePixelRatio}).then(canvas => {
          let dataURL = canvas.toDataURL("image/png");
          // console.log(dataURL, 111)
          resolve(dataURL)
        });

      })
    },


    busModel (a) {
      threeObj.groupModel = a
      threeObj.scene.add( threeObj.groupModel )
      this.resetXYZ()

      this.modelPlane[0].constant = this.ct.maxZ
      this.render();
    },
    _w_h () {
      let _w = this.$refs.ctBox.offsetWidth, _h = this.$refs.ctBox.offsetHeight
      let _w2 = 0, _h2 = 0
      if (_w >= _h) {
        // 横
        this.isLandscape = true
        _w2 = _w/2
        _h2 = _h
      } else {
        // 竖
        this.isLandscape = false
        _w2 = _w
        _h2 = _h/2
      }
      return {w: _w2, h: _h2}
    },
    onWindowResize () {
      const win = this._w_h()
      ctCanvas.width = win.w
      ctCanvas.height = win.h
      this.showImage(this.ct.indexZ)


      threeObj.camera.aspect = win.w/win.h;
      threeObj.camera.updateProjectionMatrix();
      threeObj.renderer.setSize( win.w, win.h );
      this.render();
    },
  },
  beforeDestroy() {
  },
}
</script>
<style scoped lang="less">
.ctView {
  height: calc(100% - 50px);
  // height: 100%;
  padding-top: 50px;
  overflow: hidden;
  background-color: #000;
  .v-header .header .infoBox .feature {
    color: #fff;
  }
  .ctBox {
    height: 100%;
    // height: calc(100% - 50px);
    display: flex;
    .screen3d,.screenct {
      flex: 1;
      overflow: hidden;
    }
  }
}
</style>
